/* 
    变量提升 var web = "hdr.com" 这会有两步，第一var web; 第二web= "hdr.com"
    所以浏览器会解析成这样
    var web;
    console.log(web); // 输出undefined
    web = "hdr.com";

    // 函数里的变量提升
    function fn() {
        var web;
        if (false) {
            web = "www.baidu.com";
        }
            console.log("函数里的变量提升", web);
    }
    fn();


    利用let 和const 可以解决
    必须在声明之后去使用，并不可以在声明之前使用，这里会产生一个临时性死区tdz

*/
/*
console.log(web);
var web = "hdr.com";

function fn() {
  if (false) {
    var web = "www.baidu.com";
  }
  console.log("函数里的变量提升", web);
}
fn();*/

// 就近原则
/*const web = "www.baidu.com";

function fn() {
  const web = "chenyixun";
  function ab() {
    const web = "houdunrne.com";
    console.log(web);
  }
  ab();
  console.log(web);
}
fn();
console.log(web);*/

// 全局污染 作用域
/*
// 全局污染 比如你在导入一个别人写的js库，它并没有用关键字声明例如var let const 这时候你并不知道，你也用了它
function ab() {
  web = "const.com";
}
web = "www.baidu.com";
ab();
console.log(web); // 明明声明的是www.baidu.com 为什么打印的是const.com，这就给我们带来了困扰了 解决方案两种，1.严格模式  2.补上关键字let var const

// let, const 具有块级作用域
{
  let $ = (window.$ = {});
  $.web = "www.baidu.com";
  let url = "hdc.ms";
  $.getUrl = function () {
    return getUrl;
  };
}

// 立即执行函数 避免全局污染
(function () {
  var $ = (window.$ = {});
  $.web = "www.baidu.com";
  var url = "hdc.ms";
  $.getUrl = function () {
    return getUrl;
  };
}).bind(window)();*/

// var const let区别
/*
// const常量声明一般大写 存在不可以修改地址，这里的前提是在同一块作用域下，函数作用域，块级作用域，全局作用域
// 其实就是对应的地址是不可以修改的，URL指向一个地址，但是你又让它指向另一个地址是不可以的
const URL = "https://www.baidu.com"; // 全局作用域
// const URL = "www.douyindiaokao.com";
{
  const URL = "www.hudurne.com"; // 块级作用域
  console.log(URL);
}
console.log(URL);

const CONFIG = {}; // 开辟了一个内存空间
CONFIG.web = "www.baidu.com"; // 修改内存空间里面的值，其实并没有改CONFIG那对应的地址。不是吗
console.log(CONFIG.web);

// 利用var声明的变量会被挂载在全局对象window上 但是let 和 const 并不会，假如你用var声明的变量名字刚好和window对象中的某个一模一样这样子会造成很大麻烦
// var a = 33;
// console.log(window);
// var screenLeft = 88;
// console.log(window.screenLeft);

// let和 const 并不可以重复声明 会报错提示
var a = 33;
var a = 44;
console.log(a);
let b = 30;
let b = 100;
console.log(b);*/

//变量冻结, 传值 和 传址, undefined 和 null的区别
/*
// 变量冻结 当你希望一个对象不被修改你可以使用Object.freeze() 如果你想让他提示错误可以加上use strict严格模式
"use strict";
const HOST = {
  url: "https://www.houdunren.com/api/v1",
  post: 443,
};
Object.freeze(HOST);
// HOST.post = 90;
console.log(HOST);

// 传值 和 传址, 可以这样理解，对象内存空间太大了，电脑不太想给你开辟新的空间，但是常规的变量是可以开辟新空间
let a = 1;
let b = a;
console.log(a, b);
b = 3;
console.log(a, b);

let e = { name: "jason" };
let f = e;
console.log(e, f);
f.name = "xxx";
console.log(e, f);

let obj = null;
let name = undefined;
if (!obj) console.log("object");
*/

// 严格模式 use strict 该模式会对其作用域和及其子作用域进行限定， 看例子
/*
function show() {
  "use strict"; // 向下兼容
  var public = 30; // 对关键字进行限制 public or class
  console.log(public);

  function handle() {
    web = "hdrcm.com";
  }
  handle();
}
show();
*/
